<template>
  <div class="file-upload">
    <el-upload
      ref="uploadRef"
      :action="uploadUrl"
      :http-request="autoUpload ? handleUpload : () => {}"
      :auto-upload="autoUpload"
      :before-upload="beforeUpload"
      :on-success="onSuccess"
      :on-error="onError"
      :on-progress="onProgress"
      :on-remove="onRemove"
      :on-change="onChange"
      :file-list="fileList"
      :multiple="multiple"
      :accept="accept"
      :limit="limit"
      :show-file-list="showFileList"
      :drag="drag"
      :disabled="disabled"
      v-bind="$attrs"
    >
      <template v-if="drag">
        <div class="drag-area">
          <el-icon class="el-icon--upload"><upload-filled /></el-icon>
          <div class="el-upload__text">
            将文件拖到此处，或<em>点击上传</em>
          </div>
          <div class="el-upload__tip" v-if="tip">{{ tip }}</div>
        </div>
      </template>
      <template v-else>
        <slot name="trigger">
          <el-button type="primary" :disabled="disabled">
            <el-icon><upload-filled /></el-icon>
            {{ buttonText }}
          </el-button>
        </slot>
      </template>
      
      <template #tip v-if="tip && !drag">
        <div class="el-upload__tip">{{ tip }}</div>
      </template>
    </el-upload>

    <!-- 手动上传控制按钮 -->
    <div v-if="!autoUpload && internalFileList.length > 0" class="upload-controls">
      <el-button 
        type="primary" 
        :loading="uploading" 
        @click="startUpload"
        :disabled="!hasReadyFiles"
      >
        <el-icon><upload-filled /></el-icon>
        {{ uploading ? '上传中...' : '开始上传' }}
      </el-button>
      <el-button 
        v-if="hasReadyFiles" 
        @click="clearAllFiles"
      >
        清空文件
      </el-button>
    </div>

    <!-- 自定义文件列表 -->
    <div v-if="showCustomFileList && internalFileList.length > 0" class="custom-file-list">
      <div
        v-for="(file, index) in internalFileList"
        :key="file.uid || index"
        class="file-item"
        :class="{ 'is-uploading': file.status === 'uploading' }"
      >
        <div class="file-info">
          <el-icon class="file-icon">
            <document />
          </el-icon>
          <div class="file-details">
            <div class="file-name" :title="file.name">{{ file.name }}</div>
            <div class="file-size">{{ formatFileSize(file.size) }}</div>
          </div>
        </div>
        
        <div class="file-actions">
          <el-progress
            v-if="file.status === 'uploading'"
            :percentage="file.percentage || 0"
            :show-text="false"
            class="progress"
          />
          <div v-else class="action-buttons">
            <el-button
              v-if="file.response?.success && showDownload"
              type="text"
              size="small"
              @click="downloadFile(file)"
            >
              <el-icon><download /></el-icon>
            </el-button>
            <el-button
              type="text"
              size="small"
              @click="removeFile(index)"
              class="remove-btn"
            >
              <el-icon><delete /></el-icon>
            </el-button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { UploadFilled, Document, Download, Delete } from '@element-plus/icons-vue'
import { fileApi } from '@/api/file'
import type { UploadFile, UploadRawFile, UploadRequestOptions } from 'element-plus'

interface FileUploadProps {
  // 基础配置
  modelValue?: UploadFile[]
  multiple?: boolean
  accept?: string
  limit?: number
  maxSize?: number // MB
  buttonText?: string
  tip?: string
  drag?: boolean
  disabled?: boolean
  
  // 业务配置
  businessType?: string
  businessKey?: string
  
  // 显示配置
  showFileList?: boolean
  showCustomFileList?: boolean
  showDownload?: boolean
  
  // 上传配置
  autoUpload?: boolean
  uploadUrl?: string
}

interface FileUploadEmits {
  (e: 'update:modelValue', files: UploadFile[]): void
  (e: 'success', file: UploadFile, response: any): void
  (e: 'error', error: any, file: UploadFile): void
  (e: 'progress', event: any, file: UploadFile): void
  (e: 'remove', file: UploadFile, index: number): void
  (e: 'exceed', files: File[], fileList: UploadFile[]): void
}

const props = withDefaults(defineProps<FileUploadProps>(), {
  multiple: false,
  accept: '*/*',
  limit: 10,
  maxSize: 100, // 100MB
  buttonText: '选择文件',
  tip: '',
  drag: false,
  disabled: false,
  businessType: 'general',
  businessKey: '',
  showFileList: true,
  showCustomFileList: false,
  showDownload: true,
  autoUpload: true,
  uploadUrl: ''
})

const emit = defineEmits<FileUploadEmits>()

const uploadRef = ref()
const internalFileList = ref<UploadFile[]>([])
const uploading = ref(false)

// 计算属性
const fileList = computed({
  get: () => props.modelValue || internalFileList.value,
  set: (val) => {
    internalFileList.value = val
    emit('update:modelValue', val)
  }
})

// 是否有待上传的文件
const hasReadyFiles = computed(() => {
  return internalFileList.value.some(file => file.status === 'ready')
})

// 监听外部文件列表变化
watch(
  () => props.modelValue,
  (newVal) => {
    if (newVal) {
      internalFileList.value = [...newVal]
    }
  },
  { immediate: true }
)

// 文件上传前的检查
const beforeUpload = (rawFile: UploadRawFile): boolean => {
  // 检查文件大小
  if (rawFile.size > props.maxSize * 1024 * 1024) {
    ElMessage.error(`文件大小不能超过 ${props.maxSize}MB`)
    return false
  }
  
  // 检查文件类型
  if (props.accept !== '*/*') {
    const acceptTypes = props.accept.split(',').map(type => type.trim())
    const fileExtension = '.' + rawFile.name.split('.').pop()?.toLowerCase()
    const mimeType = rawFile.type
    
    const isAccepted = acceptTypes.some(type => {
      if (type.startsWith('.')) {
        return type === fileExtension
      } else if (type.includes('*')) {
        return mimeType.startsWith(type.replace('*', ''))
      } else {
        return type === mimeType
      }
    })
    
    if (!isAccepted) {
      ElMessage.error(`不支持的文件类型，只支持：${props.accept}`)
      return false
    }
  }
  
  return true
}

// 自定义上传方法
const handleUpload = async (options: UploadRequestOptions): Promise<void> => {
  try {
    const response = await fileApi.uploadFile(
      options.file,
      props.businessType,
      props.businessKey
    )
    
    options.onSuccess(response, options.file)
  } catch (error: any) {
    options.onError(error)
  }
}

// 上传成功回调
const onSuccess = (response: any, file: UploadFile) => {
  file.response = response
  emit('success', file, response)
}

// 上传失败回调
const onError = (error: any, file: UploadFile) => {
  ElMessage.error(error?.message || '上传失败')
  emit('error', error, file)
}

// 上传进度回调
const onProgress = (event: any, file: UploadFile) => {
  emit('progress', event, file)
}

// 移除文件回调
const onRemove = (file: UploadFile) => {
  const index = fileList.value.findIndex(item => item.uid === file.uid)
  if (index > -1) {
    emit('remove', file, index)
  }
}

// 文件状态变化回调（手动上传模式）
const onChange = (file: UploadFile, fileList: UploadFile[]) => {
  if (!props.autoUpload) {
    // 手动上传模式，将文件状态设置为ready
    file.status = 'ready'
    internalFileList.value = [...fileList]
    emit('update:modelValue', internalFileList.value)
  }
}

// 开始手动上传
const startUpload = async () => {
  if (uploading.value) return
  
  uploading.value = true
  const readyFiles = internalFileList.value.filter(file => file.status === 'ready')
  
  for (const file of readyFiles) {
    try {
      file.status = 'uploading'
      file.percentage = 0
      
      const response = await fileApi.uploadFile(
        file.raw as File,
        props.businessType,
        props.businessKey,
        (progressEvent) => {
          // 更新上传进度
          if (progressEvent.lengthComputable) {
            file.percentage = Math.round((progressEvent.loaded * 100) / progressEvent.total)
          }
        }
      )
      
      file.status = 'success'
      file.response = response
      file.percentage = 100
      emit('success', file, response)
      
    } catch (error: any) {
      file.status = 'fail'
      emit('error', error, file)
    }
  }
  
  uploading.value = false
}

// 清空所有文件
const clearAllFiles = () => {
  internalFileList.value = []
  emit('update:modelValue', [])
  uploadRef.value?.clearFiles()
}

// 移除文件
const removeFile = async (index: number) => {
  const file = internalFileList.value[index]
  
  try {
    await ElMessageBox.confirm('确定要删除该文件吗？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    
    // 如果文件已上传成功，调用删除API
    if (file.response?.success && file.response?.data?.fileId) {
      try {
        await fileApi.deleteFile(file.response.data.fileId)
      } catch (error) {
        console.warn('删除服务器文件失败:', error)
      }
    }
    
    internalFileList.value.splice(index, 1)
    emit('remove', file, index)
    
  } catch {
    // 用户取消删除
  }
}

// 下载文件
const downloadFile = async (file: UploadFile) => {
  if (!file.response?.data?.fileId) {
    ElMessage.error('文件信息不完整，无法下载')
    return
  }
  
  try {
    await fileApi.downloadFile(file.response.data.fileId)
  } catch (error: any) {
    ElMessage.error(error?.message || '下载失败')
  }
}

// 格式化文件大小
const formatFileSize = (size?: number): string => {
  if (!size) return '0 B'
  
  const units = ['B', 'KB', 'MB', 'GB']
  let unitIndex = 0
  let fileSize = size
  
  while (fileSize >= 1024 && unitIndex < units.length - 1) {
    fileSize /= 1024
    unitIndex++
  }
  
  return `${fileSize.toFixed(1)} ${units[unitIndex]}`
}

// 清空文件列表
const clearFiles = () => {
  uploadRef.value?.clearFiles()
  internalFileList.value = []
  emit('update:modelValue', [])
}

// 手动上传
const submit = () => {
  uploadRef.value?.submit()
}

// 暴露方法给父组件
defineExpose({
  clearFiles,
  submit,
  uploadRef
})
</script>

<!-- 样式已迁移到 @/styles/modules/file.scss -->
